ããã³ããšã³ããã¹ããã©ãããïŒãŠããããçµ±åããšã³ãããŒãšã³ã(E2E)ãã¹ãïŒã®å æ¬çã¬ã€ããå埩åãšä¿¡é Œæ§ã®é«ãWebã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®ãã¹ããã©ã¯ãã£ã¹ãšæŠç¥ãåŠã³ãŸãã
ããã³ããšã³ããã¹ããã©ãããïŒå ç¢ãªã¢ããªã±ãŒã·ã§ã³ã®ããã®ãŠããããçµ±åãE2EæŠç¥
仿¥ã®ããŒã¹ã®éããœãããŠã§ã¢éçºã®äžçã§ã¯ãããã³ããšã³ãã¢ããªã±ãŒã·ã§ã³ã®å質ãšä¿¡é Œæ§ã確ä¿ããããšãæãéèŠã§ããé©åã«æ§æããããã¹ãæŠç¥ã¯ããã°ãæ©æã«çºèŠãããªã°ã¬ãã·ã§ã³ãé²ããã·ãŒã ã¬ã¹ãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸããããã«äžå¯æ¬ ã§ããããã³ããšã³ããã¹ããã©ãããã¯ããã¹ãã®åãçµã¿ãæŽçããå¹çã«çŠç¹ãåœãŠããã¹ãã«ãã¬ããžãæå€§åããããã®è²Žéãªãã¬ãŒã ã¯ãŒã¯ãæäŸããŸãããã®å æ¬çãªã¬ã€ãã§ã¯ããã©ãããã®åå±€ïŒãŠããããçµ±åããšã³ãããŒãšã³ãïŒE2EïŒãã¹ãïŒãæãäžãããã®ç®çãå©ç¹ãããã³å®è·µçãªå®è£ ã«ã€ããŠæ¢ããŸãã
ãã¹ããã©ããããçè§£ãã
åœåMike Cohnã«ãã£ãŠåºãããããã¹ããã©ãããã¯ããœãããŠã§ã¢ãããžã§ã¯ãã«ãããããŸããŸãªçš®é¡ã®ãã¹ãã®çæ³çãªæ¯çãèŠèŠçã«è¡šãããã®ã§ãããã©ãããã®åå°ã¯å€æ°ã®ãŠããããã¹ãã§æ§æãããæ¬¡ã«å°æ°ã®çµ±åãã¹ãããããŠé ç¹ã«ã¯ããå°æ°ã®E2Eãã¹ããé 眮ãããŸãããã®åœ¢ç¶ã®èåŸã«ããè«ççæ ¹æ ã¯ããŠããããã¹ãã¯éåžžãçµ±åãã¹ããE2Eãã¹ããšæ¯èŒããŠãäœæãå®è¡ãä¿å®ãé«éã§ãããããå æ¬çãªãã¹ãã«ãã¬ããžãéæããããã®ããè²»çšå¯Ÿå¹æã®é«ãæ¹æ³ã§ãããšããããšã§ãã
å ã®ãã©ãããã¯ããã¯ãšã³ããšAPIãã¹ãã«çŠç¹ãåœãŠãŠããŸãããããã®ååã¯ããã³ããšã³ãã«ã容æã«é©å¿ã§ããŸããåå±€ãããã³ããšã³ãéçºã«ã©ã®ããã«é©çšããããã以äžã«ç€ºããŸãã
- ãŠããããã¹ãïŒåã ã®ã³ã³ããŒãã³ãã颿°ã®æ©èœãåç¬ã§æ€èšŒããŸãã
- çµ±åãã¹ãïŒã³ã³ããŒãã³ããã¢ãžã¥ãŒã«ãªã©ãã¢ããªã±ãŒã·ã§ã³ã®ããŸããŸãªéšåãæ£ãã飿ºããŠåäœããããšã確èªããŸãã
- E2Eãã¹ãïŒå®éã®ãŠãŒã¶ãŒã€ã³ã¿ã©ã¯ã·ã§ã³ãã·ãã¥ã¬ãŒãããŠãã¢ããªã±ãŒã·ã§ã³å šäœã®ãããŒãæåããæåŸãŸã§æ€èšŒããŸãã
ãã¹ããã©ãããã®ã¢ãããŒããæ¡çšããããšã§ãããŒã ã¯ãã¹ãã®åãçµã¿ã«åªå é äœãä»ããå ç¢ã§ä¿¡é Œæ§ã®é«ãããã³ããšã³ãã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®æãå¹ççã§åœ±é¿åã®ãããã¹ãææ³ã«éäžããããšãã§ããŸãã
ãŠããããã¹ãïŒå質ã®åºç€
ãŠããããã¹ããšã¯ïŒ
ãŠããããã¹ãã¯ã颿°ãã³ã³ããŒãã³ããã¢ãžã¥ãŒã«ãªã©ã®åã ã®ã³ãŒãåäœãåç¬ã§ãã¹ãããããšãå«ã¿ãŸãããã®ç®çã¯ãç¹å®ã®å ¥åãäžããããããŸããŸãªæ¡ä»¶äžã§åãŠããããæåŸ ã©ããã«åäœããããšã確èªããããšã§ããããã³ããšã³ãéçºã®æèã§ã¯ããŠããããã¹ãã¯éåžžãåã ã®ã³ã³ããŒãã³ãã®ããžãã¯ãšåäœã®ãã¹ãã«çŠç¹ãåœãŠãããããæ£ããã¬ã³ããªã³ã°ããããŠãŒã¶ãŒã®ã€ã³ã¿ã©ã¯ã·ã§ã³ã«é©åã«å¿çããããšã確èªããŸãã
ãŠããããã¹ãã®å©ç¹
- æ©æã®ãã°æ€åºïŒãŠããããã¹ãã¯ãéçºãµã€ã¯ã«ã®æ©ã段éã§ãã°ãçºèŠããã¢ããªã±ãŒã·ã§ã³ã®ä»ã®éšåã«åºããã®ãé²ãããšãã§ããŸãã
- ã³ãŒãå質ã®åäžïŒãŠããããã¹ããäœæããããšã§ãéçºè ã¯ããã¯ãªãŒã³ã§ãããã¢ãžã¥ãŒã«åãããããã¹ãããããã³ãŒããæžãããã«ãªããŸãã
- è¿ éãªãã£ãŒãããã¯ã«ãŒãïŒãŠããããã¹ãã¯éåžžãå®è¡ãé«éã§ãããããéçºè ã¯ã³ãŒãã®å€æŽã«å¯ŸããŠè¿ éãªãã£ãŒãããã¯ãåŸãããšãã§ããŸãã
- ãããã°æéã®ççž®ïŒãã°ãèŠã€ãã£ãå ŽåããŠããããã¹ãã¯åé¡ã®æ£ç¢ºãªå Žæãç¹å®ããã®ã«åœ¹ç«ã¡ããããã°æéãççž®ããŸãã
- ã³ãŒã倿Žãžã®èªä¿¡ã®åäžïŒãŠããããã¹ãã¯ã»ãŒããã£ããããæäŸããéçºè ã¯æ¢åã®æ©èœãå£ããªãããšã確信ããŠãèªä¿¡ãæã£ãŠã³ãŒãããŒã¹ã«å€æŽãå ããããšãã§ããŸãã
- ããã¥ã¡ã³ãïŒãŠããããã¹ãã¯ã³ãŒãã®ããã¥ã¡ã³ããšããŠæ©èœããåãŠããããã©ã®ããã«äœ¿çšãããããšãæå³ããŠãããã瀺ããŸãã
ãŠããããã¹ãã®ããã®ããŒã«ãšãã¬ãŒã ã¯ãŒã¯
ããã³ããšã³ãã³ãŒãã®ãŠããããã¹ãã«ã¯ãããã€ãã®äººæ°ã®ããããŒã«ãšãã¬ãŒã ã¯ãŒã¯ãå©çšå¯èœã§ãã
- JestïŒFacebookã«ãã£ãŠéçºãããåºã䜿çšãããŠããJavaScriptãã¹ããã¬ãŒã ã¯ãŒã¯ã§ããã®ã·ã³ãã«ããé床ãã¢ããã³ã°ãã³ãŒãã«ãã¬ããžãªã©ã®çµã¿èŸŒã¿æ©èœã§ç¥ãããŠããŸããJestã¯ç¹ã«Reactãšã³ã·ã¹ãã ã§äººæ°ããããŸãã
- MochaïŒæè»ã§æ¡åŒµæ§ã®é«ãJavaScriptãã¹ããã¬ãŒã ã¯ãŒã¯ã§ãéçºè ã¯ç¬èªã®ã¢ãµãŒã·ã§ã³ã©ã€ãã©ãªïŒäŸïŒChaiïŒãã¢ããã³ã°ã©ã€ãã©ãªïŒäŸïŒSinon.JSïŒãéžæã§ããŸãã
- JasmineïŒJavaScriptåãã®ããã€ãã¢é§åéçºïŒBDDïŒãã¹ããã¬ãŒã ã¯ãŒã¯ã§ãã¯ãªãŒã³ãªæ§æãšå æ¬çãªæ©èœã»ããã§ç¥ãããŠããŸãã
- KarmaïŒè€æ°ã®ãã©ãŠã¶ã§ãã¹ããå®è¡ã§ãããã¹ãã©ã³ããŒã§ãã¯ãã¹ãã©ãŠã¶ã®äºææ§ãã¹ããæäŸããŸãã
广çãªãŠããããã¹ãã®æžãæ¹
广çãªãŠããããã¹ããäœæããããã®ãã¹ããã©ã¯ãã£ã¹ãããã€ã玹ä»ããŸãã
- äžåºŠã«äžã€ã®ããšããã¹ãããïŒåãŠããããã¹ãã¯ããŠãããã®æ©èœã®åäžã®åŽé¢ããã¹ãããããšã«çŠç¹ãåœãŠãã¹ãã§ãã
- 説æçãªãã¹ãåã䜿çšããïŒãã¹ãåã¯ãäœããã¹ãããŠããããæç¢ºã«èª¬æããå¿ èŠããããŸããäŸãã°ãã2ã€ã®æ°å€ã®æ£ããåèšãè¿ãã¹ããã¯è¯ããã¹ãåã§ãã
- ç¬ç«ãããã¹ããæžãïŒåãã¹ãã¯ä»ã®ãã¹ãããç¬ç«ããŠããã¹ãã§ãããå®è¡ãããé åºãçµæã«åœ±é¿ããªãããã«ããŸãã
- ã¢ãµãŒã·ã§ã³ã䜿çšããŠæåŸ ãããåäœãæ€èšŒããïŒã¢ãµãŒã·ã§ã³ã䜿çšããŠããŠãããã®å®éã®åºåãæåŸ ãããåºåãšäžèŽããããšã確èªããŸãã
- å€éšäŸåé¢ä¿ãã¢ãã¯ããïŒã¢ããã³ã°ã䜿çšããŠããã¹ã察象ã®ãŠããããAPIåŒã³åºããããŒã¿ããŒã¹ã€ã³ã¿ã©ã¯ã·ã§ã³ãªã©ã®å€éšäŸåé¢ä¿ããåé¢ããŸãã
- ã³ãŒãã®åã«ãã¹ããæžãïŒãã¹ãé§åéçºïŒïŒã³ãŒããæžãåã«ãã¹ããæžããã¹ãé§åéçºïŒTDDïŒã¢ãããŒãã®æ¡çšãæ€èšããŠãã ãããããã«ãããããè¯ãã³ãŒããèšèšããã³ãŒãããã¹ãå¯èœã§ããããšã確èªã§ããŸãã
äŸïŒJestã䜿çšããReactã³ã³ããŒãã³ãã®ãŠããããã¹ã
ã«ãŠã³ãã衚瀺ãããŠãŒã¶ãŒã墿žãããããšãã§ãã`Counter`ãšããåçŽãªReactã³ã³ããŒãã³ãããããšããŸãã
// Counter.js
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
const decrement = () => {
setCount(count - 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
);
}
export default Counter;
以äžã¯ãJestã䜿çšããŠãã®ã³ã³ããŒãã³ãã®ãŠããããã¹ããäœæããæ¹æ³ã§ãã
// Counter.test.js
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import Counter from './Counter';
describe('Counter Component', () => {
it('should render the initial count correctly', () => {
const { getByText } = render(<Counter />);
expect(getByText('Count: 0')).toBeInTheDocument();
});
it('should increment the count when the increment button is clicked', () => {
const { getByText } = render(<Counter />);
const incrementButton = getByText('Increment');
fireEvent.click(incrementButton);
expect(getByText('Count: 1')).toBeInTheDocument();
});
it('should decrement the count when the decrement button is clicked', () => {
const { getByText } = render(<Counter />);
const decrementButton = getByText('Decrement');
fireEvent.click(decrementButton);
expect(getByText('Count: -1')).toBeInTheDocument();
});
});
ãã®äŸã¯ãJestãš`@testing-library/react`ã䜿çšããŠã³ã³ããŒãã³ããã¬ã³ããªã³ã°ãããã®èŠçŽ ãšå¯Ÿè©±ããã³ã³ããŒãã³ããæåŸ ã©ããã«åäœããããšãã¢ãµãŒãããæ¹æ³ã瀺ããŠããŸãã
çµ±åãã¹ãïŒã®ã£ãããåãã
çµ±åãã¹ããšã¯ïŒ
çµ±åãã¹ãã¯ãã³ã³ããŒãã³ããã¢ãžã¥ãŒã«ããµãŒãã¹ãªã©ãã¢ããªã±ãŒã·ã§ã³ã®ç°ãªãéšåéã®çžäºäœçšãæ€èšŒããããšã«çŠç¹ãåœãŠãŠããŸãããã®ç®çã¯ããããã®ç°ãªãéšåãæ£ãã飿ºããŠåäœããããŒã¿ããããã®éãã·ãŒã ã¬ã¹ã«æµããããšã確èªããããšã§ããããã³ããšã³ãéçºã§ã¯ãçµ±åãã¹ãã¯éåžžãã³ã³ããŒãã³ãéã®çžäºäœçšãããã³ããšã³ããšããã¯ãšã³ãAPIéã®çžäºäœçšããŸãã¯ããã³ããšã³ãã¢ããªã±ãŒã·ã§ã³å ã®ç°ãªãã¢ãžã¥ãŒã«éã®çžäºäœçšããã¹ãããããšãå«ã¿ãŸãã
çµ±åãã¹ãã®å©ç¹
- ã³ã³ããŒãã³ãã®çžäºäœçšãæ€èšŒããïŒçµ±åãã¹ãã¯ãã³ã³ããŒãã³ããæåŸ ã©ããã«é£æºããŠåäœããããšã確èªããäžé©åãªããŒã¿æž¡ããéä¿¡ãããã³ã«ããçããå¯èœæ§ã®ããåé¡ãæããŸãã
- ã€ã³ã¿ãŒãã§ãŒã¹ãšã©ãŒãç¹å®ããïŒçµ±åãã¹ãã¯ãäžæ£ãªAPIãšã³ããã€ã³ããããŒã¿åœ¢åŒãªã©ãã·ã¹ãã ã®ç°ãªãéšåéã®ã€ã³ã¿ãŒãã§ãŒã¹ã®ãšã©ãŒãç¹å®ã§ããŸãã
- ããŒã¿ãããŒãæ€èšŒããïŒçµ±åãã¹ãã¯ãããŒã¿ãã¢ããªã±ãŒã·ã§ã³ã®ç°ãªãéšåéã§æ£ããæµããããšãæ€èšŒããããŒã¿ãæåŸ ã©ããã«å€æããã³åŠçãããããšã確èªããŸãã
- ã·ã¹ãã ã¬ãã«ã®é害ã®ãªã¹ã¯ãäœæžããïŒéçºãµã€ã¯ã«ã®æ©ã段éã§çµ±åã®åé¡ãç¹å®ããŠä¿®æ£ããããšã«ãããæ¬çªç°å¢ã§ã®ã·ã¹ãã ã¬ãã«ã®é害ã®ãªã¹ã¯ãäœæžã§ããŸãã
çµ±åãã¹ãã®ããã®ããŒã«ãšãã¬ãŒã ã¯ãŒã¯
ããã³ããšã³ãã³ãŒãã®çµ±åãã¹ãã«ã¯ãããã€ãã®ããŒã«ãšãã¬ãŒã ã¯ãŒã¯ã䜿çšã§ããŸãã
- React Testing LibraryïŒReactã³ã³ããŒãã³ãã®ãŠããããã¹ãã«ãã䜿çšãããŸãããReact Testing Libraryã¯çµ±åãã¹ãã«ãé©ããŠãããã³ã³ããŒãã³ããäºãã«ããŸãDOMãšã©ã®ããã«çžäºäœçšãããããã¹ãã§ããŸãã
- Vue Test UtilsïŒVue.jsã³ã³ããŒãã³ãããã¹ãããããã®ãŠãŒãã£ãªãã£ãæäŸããã³ã³ããŒãã³ãã®ããŠã³ããèŠçŽ ãšã®å¯Ÿè©±ãããã³ãã®åäœã®ã¢ãµãŒãæ©èœãå«ã¿ãŸãã
- CypressïŒåŒ·åãªãšã³ãããŒãšã³ããã¹ããã¬ãŒã ã¯ãŒã¯ã§ãããçµ±åãã¹ãã«ã䜿çšã§ããããã³ããšã³ããšããã¯ãšã³ãAPIéã®çžäºäœçšããã¹ãã§ããŸãã
- SupertestïŒHTTPãªã¯ãšã¹ãããã¹ãããããã®é«ã¬ãã«ã®æœè±¡åã§ãããMochaãJestãªã©ã®ãã¹ããã¬ãŒã ã¯ãŒã¯ãšçµã¿åãããŠAPIãšã³ããã€ã³ãããã¹ãããããã«ãã䜿çšãããŸãã
广çãªçµ±åãã¹ãã®æžãæ¹
广çãªçµ±åãã¹ããäœæããããã®ãã¹ããã©ã¯ãã£ã¹ãããã€ã玹ä»ããŸãã
- çžäºäœçšã«çŠç¹ãåœãŠãïŒçµ±åãã¹ãã¯ãåã ã®ãŠãããã®å éšå®è£ ã®è©³çްããã¹ãããã®ã§ã¯ãªããã¢ããªã±ãŒã·ã§ã³ã®ç°ãªãéšåéã®çžäºäœçšããã¹ãããããšã«çŠç¹ãåœãŠãã¹ãã§ãã
- çŸå®çãªããŒã¿ã䜿çšããïŒçµ±åãã¹ãã§çŸå®çãªããŒã¿ã䜿çšããŠãçŸå®äžçã®ã·ããªãªãã·ãã¥ã¬ãŒãããæœåšçãªããŒã¿é¢é£ã®åé¡ãæããŸãã
- å€éšäŸåé¢ä¿ã®ã¢ãã¯ã¯æ§ããã«äœ¿çšããïŒã¢ããã³ã°ã¯ãŠããããã¹ãã«äžå¯æ¬ ã§ãããçµ±åãã¹ãã§ã¯æ§ããã«äœ¿çšããå¿ èŠããããŸããå¯èœãªéããã³ã³ããŒãã³ããšãµãŒãã¹éã®å®éã®çžäºäœçšããã¹ãããããã«ããŠãã ããã
- äž»èŠãªãŠãŒã¹ã±ãŒã¹ãã«ããŒãããã¹ããæžãïŒã¢ããªã±ãŒã·ã§ã³ã§æãéèŠãªãŠãŒã¹ã±ãŒã¹ãšã¯ãŒã¯ãããŒãã«ããŒããçµ±åãã¹ãã®äœæã«çŠç¹ãåœãŠãŸãã
- ãã¹ãç°å¢ã䜿çšããïŒçµ±åãã¹ãã«ã¯ãéçºç°å¢ãæ¬çªç°å¢ãšã¯å¥ã®å°çšã®ãã¹ãç°å¢ã䜿çšããŸããããã«ããããã¹ããåé¢ãããä»ã®ç°å¢ã«å¹²æžããªãããšãä¿èšŒãããŸãã
äŸïŒReactã³ã³ããŒãã³ãã®ã€ã³ã¿ã©ã¯ã·ã§ã³ã®çµ±åãã¹ã
2ã€ã®Reactã³ã³ããŒãã³ã `ProductList` ãš `ProductDetails` ããããšããŸãã`ProductList` ã¯è£œåã®ãªã¹ãã衚瀺ãããŠãŒã¶ãŒã補åãã¯ãªãã¯ãããš `ProductDetails` ããã®è£œåã®è©³çްã衚瀺ããŸãã
// ProductList.js
import React, { useState } from 'react';
import ProductDetails from './ProductDetails';
function ProductList({ products }) {
const [selectedProduct, setSelectedProduct] = useState(null);
const handleProductClick = (product) => {
setSelectedProduct(product);
};
return (
<div>
<ul>
{products.map((product) => (
<li key={product.id} onClick={() => handleProductClick(product)}>
{product.name}
</li>
))}
</ul>
{selectedProduct && <ProductDetails product={selectedProduct} />}
</div>
);
}
export default ProductList;
// ProductDetails.js
import React from 'react';
function ProductDetails({ product }) {
return (
<div>
<h2>{product.name}</h2>
<p>{product.description}</p>
<p>Price: {product.price}</p>
</div>
);
}
export default ProductDetails;
以äžã¯ãReact Testing Libraryã䜿çšããŠãããã®ã³ã³ããŒãã³ãã®çµ±åãã¹ããäœæããæ¹æ³ã§ãã
// ProductList.test.js
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import ProductList from './ProductList';
const products = [
{ id: 1, name: 'Product A', description: 'Description A', price: 10 },
{ id: 2, name: 'Product B', description: 'Description B', price: 20 },
];
describe('ProductList Component', () => {
it('should display product details when a product is clicked', () => {
const { getByText } = render(<ProductList products={products} />);
const productA = getByText('Product A');
fireEvent.click(productA);
expect(getByText('Description A')).toBeInTheDocument();
});
});
ãã®äŸã¯ãReact Testing Libraryã䜿çšããŠ`ProductList`ã³ã³ããŒãã³ããã¬ã³ããªã³ã°ãã補åã«å¯ŸãããŠãŒã¶ãŒã®ã¯ãªãã¯ãã·ãã¥ã¬ãŒããã`ProductDetails`ã³ã³ããŒãã³ããæ£ããè£œåæ å ±ã§è¡šç€ºãããããšãã¢ãµãŒãããæ¹æ³ã瀺ããŠããŸãã
ãšã³ãããŒãšã³ãïŒE2EïŒãã¹ãïŒãŠãŒã¶ãŒã®èŠç¹
E2Eãã¹ããšã¯ïŒ
ãšã³ãããŒãšã³ãïŒE2EïŒãã¹ãã¯ãå®éã®ãŠãŒã¶ãŒã€ã³ã¿ã©ã¯ã·ã§ã³ãã·ãã¥ã¬ãŒãããŠãã¢ããªã±ãŒã·ã§ã³å šäœã®ãããŒãæåããæåŸãŸã§ãã¹ãããããšãå«ã¿ãŸãããã®ç®çã¯ãã¢ããªã±ãŒã·ã§ã³ã®ãã¹ãŠã®éšåãæ£ãã飿ºããŠåäœããã¢ããªã±ãŒã·ã§ã³ããŠãŒã¶ãŒã®æåŸ ãæºããããšã確èªããããšã§ããE2Eãã¹ãã¯éåžžãç°ãªãããŒãžãžã®ããã²ãŒã·ã§ã³ããã©ãŒã ã®å ¥åããã¿ã³ã®ã¯ãªãã¯ãããã³ã¢ããªã±ãŒã·ã§ã³ãæåŸ ã©ããã«å¿çããããšã®æ€èšŒãªã©ããã©ãŠã¶ã®ã€ã³ã¿ã©ã¯ã·ã§ã³ãèªååããããšãå«ã¿ãŸããE2Eãã¹ãã¯ãçŸå®çãªèšå®ã§ã¢ããªã±ãŒã·ã§ã³ãæ£ããåäœããããšã確èªããããã«ãã¹ããŒãžã³ã°ç°å¢ãŸãã¯æ¬çªç°å¢ã«è¿ãç°å¢ã§å®è¡ãããããšããããããŸãã
E2Eãã¹ãã®å©ç¹
- ã¢ããªã±ãŒã·ã§ã³å šäœã®ãããŒãæ€èšŒããïŒE2Eãã¹ãã¯ããŠãŒã¶ãŒã®æåã®ã€ã³ã¿ã©ã¯ã·ã§ã³ããæçµçãªçµæãŸã§ãã¢ããªã±ãŒã·ã§ã³å šäœã®ãããŒãæ£ããåäœããããšã確èªããŸãã
- ã·ã¹ãã ã¬ãã«ã®ãã°ãæããïŒE2Eãã¹ãã¯ãããŒã¿ããŒã¹æ¥ç¶ããããã¯ãŒã¯é å»¶ããã©ãŠã¶ã®äºææ§ã®åé¡ãªã©ããŠããããã¹ããçµ±åãã¹ãã§ã¯æããããªãå¯èœæ§ã®ããã·ã¹ãã ã¬ãã«ã®ãã°ãæããããšãã§ããŸãã
- ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæ€èšŒããïŒE2Eãã¹ãã¯ãã¢ããªã±ãŒã·ã§ã³ãã·ãŒã ã¬ã¹ã§çŽæçãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸããããšãæ€èšŒãããŠãŒã¶ãŒãç°¡åã«ç®æšãéæã§ããããšãä¿èšŒããŸãã
- æ¬çªãããã€ãžã®èªä¿¡ãæäŸããïŒE2Eãã¹ãã¯ãæ¬çªãããã€ã«å¯Ÿããé«ãã¬ãã«ã®èªä¿¡ãæäŸãããŠãŒã¶ãŒã«ãªãªãŒã¹ãããåã«ã¢ããªã±ãŒã·ã§ã³ãæ£ããåäœããŠããããšãä¿èšŒããŸãã
E2Eãã¹ãã®ããã®ããŒã«ãšãã¬ãŒã ã¯ãŒã¯
ããã³ããšã³ãã¢ããªã±ãŒã·ã§ã³ã®E2Eãã¹ãã«ã¯ãããã€ãã®åŒ·åãªããŒã«ãšãã¬ãŒã ã¯ãŒã¯ãå©çšå¯èœã§ãã
- CypressïŒäœ¿ãããããå æ¬çãªæ©èœã»ãããåªããéçºè ãšã¯ã¹ããªãšã³ã¹ã§ç¥ããã人æ°ã®E2Eãã¹ããã¬ãŒã ã¯ãŒã¯ã§ããCypressã䜿çšãããšãJavaScriptã§ãã¹ããäœæã§ããã¿ã€ã ãã©ãã«ãããã°ãèªååŸ æ©ããªã¢ã«ã¿ã€ã ãªããŒããªã©ã®æ©èœãæäŸãããŸãã
- Selenium WebDriverïŒè€æ°ã®ãã©ãŠã¶ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã§ãã©ãŠã¶ã®ã€ã³ã¿ã©ã¯ã·ã§ã³ãèªååã§ãããåºã䜿çšãããŠããE2Eãã¹ããã¬ãŒã ã¯ãŒã¯ã§ããSelenium WebDriverã¯ãJUnitãTestNGãªã©ã®ãã¹ããã¬ãŒã ã¯ãŒã¯ãšçµã¿åãããŠäœ¿çšãããããšããããããŸãã
- PlaywrightïŒMicrosoftã«ãã£ãŠéçºãããæ¯èŒçæ°ããE2Eãã¹ããã¬ãŒã ã¯ãŒã¯ã§ãé«éã§ä¿¡é Œæ§ã®é«ãã¯ãã¹ãã©ãŠã¶ãã¹ããæäŸããããã«èšèšãããŠããŸããPlaywrightã¯ãJavaScriptãTypeScriptãPythonãJavaãªã©ãè€æ°ã®ããã°ã©ãã³ã°èšèªããµããŒãããŠããŸãã
- PuppeteerïŒGoogleã«ãã£ãŠéçºãããNodeã©ã€ãã©ãªã§ããããã¬ã¹ã®ChromeãŸãã¯Chromiumãå¶åŸ¡ããããã®é«ã¬ãã«APIãæäŸããŸããPuppeteerã¯ãE2Eãã¹ãã ãã§ãªããWebã¹ã¯ã¬ã€ãã³ã°ãèªåãã©ãŒã å ¥åãªã©ã®ä»ã®ã¿ã¹ã¯ã«ã䜿çšã§ããŸãã
广çãªE2Eãã¹ãã®æžãæ¹
广çãªE2Eãã¹ããäœæããããã®ãã¹ããã©ã¯ãã£ã¹ãããã€ã玹ä»ããŸãã
- äž»èŠãªãŠãŒã¶ãŒãããŒã«çŠç¹ãåœãŠãïŒE2Eãã¹ãã¯ããŠãŒã¶ãŒç»é²ããã°ã€ã³ããã§ãã¯ã¢ãŠãããã©ãŒã ã®éä¿¡ãªã©ãã¢ããªã±ãŒã·ã§ã³ã§æãéèŠãªãŠãŒã¶ãŒãããŒããã¹ãããããšã«çŠç¹ãåœãŠãã¹ãã§ãã
- çŸå®çãªãã¹ãããŒã¿ã䜿çšããïŒE2Eãã¹ãã§çŸå®çãªãã¹ãããŒã¿ã䜿çšããŠãçŸå®äžçã®ã·ããªãªãã·ãã¥ã¬ãŒãããæœåšçãªããŒã¿é¢é£ã®åé¡ãæããŸãã
- å ç¢ã§ä¿å®å¯èœãªãã¹ããæžãïŒE2Eãã¹ãã¯ãæ³šææ·±ãæžãããªããšãäžå®å®ã§å€±æãããããªãå¯èœæ§ããããŸããæç¢ºã§èª¬æçãªãã¹ãåã䜿çšããé »ç¹ã«å€æŽãããå¯èœæ§ã®ããç¹å®ã®UIèŠçŽ ã«äŸåããã®ãé¿ããå ±éã®ãã¹ãã¹ããããã«ãã»ã«åããããã«ãã«ããŒé¢æ°ã䜿çšããŸãã
- äžè²«ããç°å¢ã§ãã¹ããå®è¡ããïŒå°çšã®ã¹ããŒãžã³ã°ç°å¢ãæ¬çªç°å¢ã«è¿ãç°å¢ãªã©ãäžè²«ããç°å¢ã§E2Eãã¹ããå®è¡ããŸããããã«ããããã¹ããç°å¢åºæã®åé¡ã®åœ±é¿ãåããªãããšãä¿èšŒãããŸãã
- CI/CDãã€ãã©ã€ã³ã«E2Eãã¹ããçµ±åããïŒCI/CDãã€ãã©ã€ã³ã«E2Eãã¹ããçµ±åããŠãã³ãŒãã®å€æŽãè¡ããããã³ã«èªåçã«å®è¡ãããããã«ããŸããããã«ããããã°ãæ©æã«çºèŠãããªã°ã¬ãã·ã§ã³ãé²ãããšãã§ããŸãã
äŸïŒCypressã䜿çšããE2Eãã¹ã
以äžã®æ©èœãåããç°¡åãªTo-Doãªã¹ãã¢ããªã±ãŒã·ã§ã³ããããšããŸãã
- ãŠãŒã¶ãŒã¯ãªã¹ãã«æ°ããTo-Doã¢ã€ãã ã远å ã§ããŸãã
- ãŠãŒã¶ãŒã¯To-Doã¢ã€ãã ãå®äºæžã¿ãšããŠããŒã¯ã§ããŸãã
- ãŠãŒã¶ãŒã¯ãªã¹ãããTo-Doã¢ã€ãã ãåé€ã§ããŸãã
以äžã¯ãCypressã䜿çšããŠãã®ã¢ããªã±ãŒã·ã§ã³ã®E2Eãã¹ããäœæããæ¹æ³ã§ãã
// cypress/integration/todo.spec.js
describe('To-Do List Application', () => {
beforeEach(() => {
cy.visit('/'); // ã¢ããªã±ãŒã·ã§ã³ãã«ãŒãURLã§å®è¡ãããŠãããšä»®å®
});
it('should add a new to-do item', () => {
cy.get('input[type="text"]').type('Buy groceries');
cy.get('button').contains('Add').click();
cy.get('li').should('contain', 'Buy groceries');
});
it('should mark a to-do item as completed', () => {
cy.get('li').contains('Buy groceries').find('input[type="checkbox"]').check();
cy.get('li').contains('Buy groceries').should('have.class', 'completed'); // å®äºããã¢ã€ãã ã«ã¯ "completed" ãšããã¯ã©ã¹ããããšä»®å®
});
it('should delete a to-do item', () => {
cy.get('li').contains('Buy groceries').find('button').contains('Delete').click();
cy.get('li').should('not.contain', 'Buy groceries');
});
});
ãã®äŸã¯ãCypressã䜿çšããŠãã©ãŠã¶ã®ã€ã³ã¿ã©ã¯ã·ã§ã³ãèªååããTo-Doãªã¹ãã¢ããªã±ãŒã·ã§ã³ãæåŸ ã©ããã«åäœããããšãæ€èšŒããæ¹æ³ã瀺ããŠããŸããCypressã¯ãDOMèŠçŽ ãšã®å¯Ÿè©±ããã®ããããã£ã®ã¢ãµãŒããããã³ãŠãŒã¶ãŒã¢ã¯ã·ã§ã³ã®ã·ãã¥ã¬ãŒã·ã§ã³ã®ããã®æµæ¢ãªAPIãæäŸããŸãã
ãã©ãããã®ãã©ã³ã¹ïŒé©åãªããã¯ã¹ãèŠã€ãã
ãã¹ããã©ãããã¯å³æ ŒãªåŠæ¹ç®ã§ã¯ãªããããŒã ããã¹ãã®åãçµã¿ã«åªå é äœãä»ããã®ãå©ããããã®ã¬ã€ãã©ã€ã³ã§ããåçš®é¡ã®ãã¹ãã®æ£ç¢ºãªæ¯çã¯ããããžã§ã¯ãã®ç¹å®ã®ããŒãºã«ãã£ãŠç°ãªãå ŽåããããŸãã
äŸãã°ãå€ãã®ããžãã¹ããžãã¯ãæã€è€éãªã¢ããªã±ãŒã·ã§ã³ã§ã¯ãããžãã¯ã培åºçã«ãã¹ããããããã«ãããé«ãæ¯çã®ãŠããããã¹ããå¿ èŠã«ãªãå ŽåããããŸãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã«éç¹ã眮ããã·ã³ãã«ãªã¢ããªã±ãŒã·ã§ã³ã§ã¯ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãæ£ããæ©èœããŠããããšã確èªããããã«ãããé«ãæ¯çã®E2Eãã¹ããæçã§ããå ŽåããããŸãã
æçµçã«ãç®æšã¯ããã¹ãã«ãã¬ããžããã¹ãé床ãããã³ãã¹ãã®ä¿å®æ§ã®éã§æé©ãªãã©ã³ã¹ãæäŸããããŠããããçµ±åãããã³E2Eãã¹ãã®é©åãªããã¯ã¹ãèŠã€ããããšã§ãã
課é¡ãšèæ ®äºé
å ç¢ãªãã¹ãæŠç¥ãå®è£ ããã«ã¯ãããã€ãã®èª²é¡ãçããå¯èœæ§ããããŸãã
- ãã¹ãã®äžå®å®ãïŒç¹ã«E2Eãã¹ãã¯ãäžå®å®ã«ãªããã¡ã§ããã€ãŸãããããã¯ãŒã¯é å»¶ãã¿ã€ãã³ã°ã®åé¡ãªã©ã®èŠå ã«ãããã©ã³ãã ã«æåããã倱æãããããããšããããŸãããã¹ãã®äžå®å®ãã«å¯ŸåŠããã«ã¯ãæ éãªãã¹ãèšèšãå ç¢ãªãšã©ãŒãã³ããªã³ã°ãããã³å Žåã«ãã£ãŠã¯ãªãã©ã€ã¡ã«ããºã ã®äœ¿çšãå¿ èŠã§ãã
- ãã¹ãã®ã¡ã³ããã³ã¹ïŒã¢ããªã±ãŒã·ã§ã³ãé²åããã«ã€ããŠãã³ãŒãããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã®å€æŽãåæ ããããã«ãã¹ããæŽæ°ããå¿ èŠãããå ŽåããããŸãããã¹ããææ°ã®ç¶æ ã«ä¿ã€ããšã¯æéã®ãããäœæ¥ã§ããããã¹ããé¢é£æ§ãæã¡ç¶ãã广çã§ããç¶ããããã«ã¯äžå¯æ¬ ã§ãã
- ãã¹ãç°å¢ã®ã»ããã¢ããïŒäžè²«ãããã¹ãç°å¢ãã»ããã¢ããããŠç¶æããããšã¯ãç¹ã«ãã«ã¹ã¿ãã¯ã®ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããå¿ èŠãããE2Eãã¹ãã«ãšã£ãŠã¯å°é£ãªå ŽåããããŸããDockerãªã©ã®ã³ã³ããåæè¡ãã¯ã©ãŠãããŒã¹ã®ãã¹ããµãŒãã¹ã䜿çšããŠããã¹ãç°å¢ã®ã»ããã¢ãããç°¡çŽ åããããšãæ€èšããŠãã ããã
- ããŒã ã®ã¹ãã«ã»ããïŒå æ¬çãªãã¹ãæŠç¥ãå®è£ ããã«ã¯ãããŸããŸãªãã¹ãæè¡ãããŒã«ã«é¢ããå¿ èŠãªã¹ãã«ãšå°éç¥èãæã€ããŒã ãå¿ èŠã§ããããŒã ã广çãªãã¹ããäœæããç¶æããããã«å¿ èŠãªã¹ãã«ãæã£ãŠããããšã確èªããããã«ããã¬ãŒãã³ã°ãšã¡ã³ã¿ãŒã·ããã«æè³ããŠãã ããã
çµè«
ããã³ããšã³ããã¹ããã©ãããã¯ããã¹ãã®åãçµã¿ãæŽçããå ç¢ã§ä¿¡é Œæ§ã®é«ãããã³ããšã³ãã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®è²Žéãªãã¬ãŒã ã¯ãŒã¯ãæäŸããŸãããŠããããã¹ããåºç€ãšããçµ±åãã¹ããšE2Eãã¹ãã§è£å®ããããšã«çŠç¹ãåœãŠãããšã§ãå æ¬çãªãã¹ãã«ãã¬ããžãéæããéçºãµã€ã¯ã«ã®æ©ã段éã§ãã°ãçºèŠããããšãã§ããŸããå æ¬çãªãã¹ãæŠç¥ãå®è£ ããããšã«ã¯èª²é¡ã䌎ãå¯èœæ§ããããŸãããã³ãŒãå質ã®åäžããããã°æéã®ççž®ãæ¬çªãããã€ãžã®èªä¿¡ã®åäžãšãã£ãå©ç¹ã¯ãã³ã¹ããã¯ããã«äžåããŸãããã¹ããã©ããããåãå ¥ããããŒã ãäžçäžã®ãŠãŒã¶ãŒãåã°ããé«å質ã®ããã³ããšã³ãã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããããã«åãäžããŸãããããããžã§ã¯ãã®ç¹å®ã®ããŒãºã«åãããŠãã©ããããé©å¿ãããã¢ããªã±ãŒã·ã§ã³ã®é²åã«åãããŠãã¹ãæŠç¥ãç¶ç¶çã«æŽç·Žãããããšãå¿ããªãã§ãã ãããå ç¢ã§ä¿¡é Œæ§ã®é«ãããã³ããšã³ãã¢ããªã±ãŒã·ã§ã³ãžã®éã®ãã¯ãåŠç¿ãé©å¿ããããŠãã¹ããã©ã¯ãã£ã¹ã®æ¹åãšããç¶ç¶çãªããã»ã¹ã§ãã